package com.mindskip.xzs.utility;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
public class CodeGen {


//    public static void main(String[] args) {
////        List<String> tableNames=new ArrayList<>();
////        List<String> tableNames= Arrays.asList("plan","time_slot","program");
////        int frontIdx=0;
////        int linkIdx=1;
////        int endIdx=2;
////        String whereCode=" where ";
////        for (int i = 0; i < tableNames.size(); i++) {
////            String frontTable = tableNames.get(frontIdx);
////            String linkTable = tableNames.get(linkIdx);
////            String backTable = tableNames.get(endIdx);
////            String  linkTableName=frontTable+"_"+backTable;
////            whereCode+="#frontTable#.id = #linkTableName#.#frontTable#_id ";
////            whereCode+="#linkTableName#. #endTable#_id = #endTable#.id ";
////        }
//        List<String> tableNames= Arrays.asList("plan","time_slot","program");
//        String whereCode = makeWhereCode(tableNames);
//        String selectCode = makeSelectCode(tableNames);
//        String fromCode = makeFromCode(tableNames);
//        System.out.println(selectCode+fromCode+whereCode);
//    }


   public   static String genBatchInsert(){
        return null;
    }

    public  void jsonLoopMakeJavaClassCode(Object object) {

        if(object instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) object;
            for (Map.Entry<String, Object> entry: jsonObject.entrySet()) {
                Object o = entry.getValue();
                if(o instanceof String) {
//                    javaClassCode+="String "+entry.getKey()+" ;\n";
//                    javaClassCode+= String.format("     String %s = \"%s\";\n",entry.getKey(),entry.getValue() );
//                    javaClassCode.append(
//                            String.format("     String %s = \"%s\";\n",
//                                    entry.getKey(),entry.getValue()
//                            ));
                    javaClassCodeBody.append(
                            String.format("     String %s = \"%s\";\n",
                                    entry.getKey(),entry.getValue()
                            ));

                    String fieldName = entry.getKey();
                    Object fieldVal= entry.getValue();
                    fromMapCodeBody.append(
                            String.format("    %s = (String)map.get(\"%s\");\n",
                                    fieldName,fieldName
                            ));
//                    System.out.println("String "+entry.getKey()+" ;");
//                    System.out.println("key:" + entry.getKey() + "，value:" + entry.getValue());
                } else {
                    jsonLoopMakeJavaClassCode(o);
                }
            }
        }
        if(object instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) object;
            for (Object o : jsonArray) {
                jsonLoopMakeJavaClassCode(o);
            }
        }
    }


//    String javaClassCode="public class  ClassName { \n";
StringBuilder javaClassCodeBody=new StringBuilder();
//    StringBuilder javaClassCode=new StringBuilder("" +
//        "import lombok.*;\n" +
//        "import javax.persistence.Entity;\n" +
//        "import javax.persistence.Table;\n" +
//        "\n" +
//        "@Data\n" +
//        "@ToString\n" +
//        "@AllArgsConstructor\n" +
//        "@NoArgsConstructor\n" +
//        "@Builder\n" +
//        "@Entity\n" +
//        "@Table\n" +
//        "public class  ClassName { \n");

    String mapListCode="List<#className#> list = maps.stream().map(map -> {\n" +
            "            #className# obj = new #className#();\n" +
            "            obj.fromMap(map);\n" +
            "            return obj;\n" +
            "        }).collect(Collectors.toList());";

//    String insertBatchCode="<insert id=\"insertBatch\">\n" +
//            "    INSERT INTO #tableName# (#cols# node_id,`type`,perf_time,pm25_h,pm10_h,temp_h,humi_h,co2_h,tvoc_h)\n" +
//            "    VALUES\n" +
//            "    <foreach collection=\"list\" close=\"\" index=\"index\" item=\"item\" open=\"\" separator=\",\">\n" +
//            "      (#values# #{item.nodeId},#{item.type},#{item.perfTime},#{item.pm25H},#{item.pm10H},#{item.tempH},#{item.humiH},#{item.co2H},#{item.tvocH})\n" +
//            "    </foreach>\n" +
//            "  </insert>";

  public  static String genInsertBatchCodeMybatis(List<String> cols, String tableName){
        String insertBatchCode="<insert id=\"insertBatch\">\n" +
                "    INSERT INTO #tableName# (#cols# )\n" +
                "    VALUES\n" +
                "    <foreach collection=\"list\" close=\"\" index=\"index\" item=\"item\" open=\"\" separator=\",\">\n" +
                "      (#values#)\n" +
                "    </foreach>\n" +
                "  </insert>";
//        String colsList=
//        for (String col : cols) {
//            col
//        }
//        String colsList = String.join(",", cols);
//        String colsList = String.join(",", cols);
        String colsList = cols.stream().map(o -> "`" + o + "`")
                .collect(Collectors.joining(","));
        String values = cols.stream().map(o -> {
            return   String.format("#{item.%s}", o);
        })  .collect(Collectors.joining(","));
        return insertBatchCode.replace("#cols#",colsList)
                .replace("#values#",values)
                .replace("#tableName#",tableName)
                ;
    }
    String javaClassCode="" +
            "import lombok.*;\n" +
            "import javax.persistence.Entity;\n" +
            "import javax.persistence.Table;\n" +
            "\n" +
            "@Data\n" +
            "@ToString\n" +
            "@AllArgsConstructor\n" +
            "@NoArgsConstructor\n" +
            "@Builder\n" +
            "@Entity\n" +
            "@Table\n" +
            "public class  ClassName { " +
            "\n" +
            "%s\n" +
            "%s" +
            "\n" +
            "}\n";

//    StringBuilder fromMapCode=new StringBuilder(" public  void fromMap(Map<String ,Object>map){\n" +
//            "         %s\n" +
//            "     }");
    StringBuilder fromMapCodeBody=new StringBuilder();
    String fromMapCode=" public  void fromMap(Map<String ,Object>map){\n" +
            "         %s\n" +
            "     }";

    public String jsonToJavaCode(String json){
        JSONObject jsonObject = JsonUtil.stringToJson(json);
//        jsonObject.forEach(o->o.ge);
        jsonLoopMakeJavaClassCode(jsonObject);
//        javaClassCode.append("\n } ");
        fromMapCode= String.format(fromMapCode, fromMapCodeBody);

        javaClassCode= String.format(javaClassCode, javaClassCodeBody,fromMapCode);
//        javaClassCode+="\n } ";

        return "";
    }
    static String makeFromCode(List<String> tableNames){
//        List<String> tableNames= Arrays.asList("plan","time_slot","program");
        int frontIdx=0;
//        int linkIdx=1;
        int backIdx=1;
//        int endIdx=2;
//        String whereCode=" where ";
//        0 1 2
        StringBuilder whereCode= new StringBuilder(" from ");
        String firstTable = tableNames.get(0);
        whereCode.append(firstTable).append(", ");
        for (int i = 0; i < tableNames.size(); i++) {
            String frontTable = tableNames.get(frontIdx);
//            String linkTable = tableNames.get(backIdx);
            String backTable = tableNames.get(backIdx);
//            String backTable = tableNames.get(endIdx);
            String linkTableName=frontTable+"_"+backTable;

//            whereCode.append(" #frontTable#,\n#linkTableName#,\n#backTable#,"
            whereCode.append(" #linkTableName#,\n#backTable#,"
                    .replace("#frontTable#", frontTable)
                    .replace("#backTable#", backTable)
                    .replace("#linkTableName#", linkTableName))
            ;
            frontIdx++;
            backIdx++;
            if(backIdx>=tableNames.size()){
                break;
            }

        }

//        whereCode.rela
        whereCode = new StringBuilder(whereCode.substring(0, whereCode.length() - 1));
        whereCode.append("\n");
//        whereCode=   whereCode.replaceFirst("and","where");

//        System.out.println(whereCode);
        return whereCode.toString();
    }

    static String makeSelectCode(List<String> tableNames){
//        List<String> tableNames= Arrays.asList("plan","time_slot","program");
        int frontIdx=0;
//        int linkIdx=1;
        int backIdx=1;
//        int endIdx=2;
//        String whereCode=" where ";
        StringBuilder whereCode= new StringBuilder(" select \n");
        String firstTable = tableNames.get(0);
        whereCode.append(firstTable+".*").append(",\n ");
        List<String> codes=new ArrayList<>();
        for (int i = 0; i < tableNames.size(); i++) {
            String frontTable = tableNames.get(frontIdx);
//            String linkTable = tableNames.get(backIdx);
            String backTable = tableNames.get(backIdx);
//            String backTable = tableNames.get(endIdx);
            String linkTableName=frontTable+"_"+backTable;
//            whereCode.append("  #frontTable#.*, \n #backTable#.*,"
            codes.add(backTable+".*");
//            whereCode.append("   #backTable#.*,"
//                    .replace("#frontTable#", frontTable)
//                    .replace("#backTable#", backTable)
//                    .replace("#linkTableName#", linkTableName))
//            ;
            frontIdx++;
            backIdx++;
            if(backIdx>=tableNames.size()){
                break;
            }
        }
//        System.out.println(codes);
        String tables = String.join(",\n", codes);
        whereCode.append(tables);
//        whereCode = new StringBuilder(whereCode.substring(0, whereCode.length() - 1));
        whereCode.append("\n");
//        System.out.println(whereCode);
        return whereCode.toString();
    }

    static String makeWhereCode(List<String> tableNames){
//        List<String> tableNames= Arrays.asList("plan","time_slot","program");
        int frontIdx=0;
//        int linkIdx=1;
        int backIdx=1;
//        int endIdx=2;
//        String whereCode=" where ";
        StringBuilder whereCode= new StringBuilder(" ");
        for (int i = 0; i < tableNames.size(); i++) {
            String frontTable = tableNames.get(frontIdx);
//            String linkTable = tableNames.get(backIdx);
            String backTable = tableNames.get(backIdx);
//            String backTable = tableNames.get(endIdx);
            String linkTableName=frontTable+"_"+backTable;
            whereCode.append(" \n and #frontTable#.id = #linkTableName#.#frontTable#_id \n and  #linkTableName#. #backTable#_id = #backTable#.id "
                    .replace("#frontTable#", frontTable)
                    .replace("#backTable#", backTable)
                    .replace("#linkTableName#", linkTableName))
            ;
            frontIdx++;
            backIdx++;
            if(backIdx>=tableNames.size()){
                break;
            }

        }

        whereCode = new StringBuilder(whereCode.toString().replaceFirst("and", "where"));

//        System.out.println(whereCode);
        return whereCode.toString();
    }


    public static void main(String[] args) {
//        Notice notice = new Notice();

//        String gen = gen(notice);
//        System.out.println(gen);

//        CodeGen codeGen = new CodeGen();
//        codeGen.genAxios(notice);
////        codeGen.axiosGetCode.so
//        System.out.println(codeGen.axiosPostCode);

//        List<String> tableNames= Arrays.asList("plan","time_slot","program");
////        String whereCode = makeWhereCode(tableNames);
////        String selectCode = makeSelectCode(tableNames);
////        String fromCode = makeFromCode(tableNames);
////        System.out.println(selectCode+fromCode+whereCode);
//        String linkedTableQuery = genLinkedTableQuery(tableNames);
//        System.out.println(linkedTableQuery);
//

        CodeGen codeGen=new CodeGen() ;
        codeGen.jsonToJavaCode(" {\n" +
                "      \"CHARACTER_MAXIMUM_LENGTH\": 255,\n" +
                "      \"TABLE_CATALOG\": \"def\",\n" +
                "      \"TABLE_SCHEMA\": \"gcsm\",\n" +
                "      \"EXTRA\": \"\",\n" +
                "      \"IS_NULLABLE\": \"YES\",\n" +
                "      \"COLUMN_KEY\": \"\",\n" +
                "      \"COLUMN_TYPE\": \"varchar(255)\",\n" +
                "      \"COLUMN_COMMENT\": \"公告状态\",\n" +
                "      \"COLLATION_NAME\": \"utf8_general_ci\",\n" +
                "      \"CHARACTER_OCTET_LENGTH\": 765,\n" +
                "      \"CHARACTER_SET_NAME\": \"utf8\",\n" +
                "      \"DATA_TYPE\": \"varchar\",\n" +
                "      \"TABLE_NAME\": \"notice\",\n" +
                "      \"COLUMN_NAME\": \"state\",\n" +
                "      \"ORDINAL_POSITION\": 4,\n" +
                "      \"PRIVILEGES\": \"select,insert,update,references\"\n" +
                "    },");
        System.out.println(codeGen.javaClassCode);
//        System.out.println(codeGen.fromMapCode);
    }

   static String genLinkedTableQuery(List<String> tableNames){
//       List<String> tableNames= Arrays.asList("plan","time_slot","program");
       String whereCode = makeWhereCode(tableNames);
       String selectCode = makeSelectCode(tableNames);
       String fromCode = makeFromCode(tableNames);
//       System.out.println(selectCode+fromCode+whereCode);
       return selectCode+fromCode+whereCode+";";
   }

    String axiosGetCode;
    String axiosPostCode;

//    public void genAxios(Object object) {
//        String tableName = getTableName(object);
//        String jsonAllFiled = ObjectToJson.Object2JsonAllFiled(object);
//
//        String axiosGetCodeTpl = "axios.get(   common.baseURL + \"/#tableName#\").then((resp) => {\n" +
//                "        if (resp && resp.code === 200) {\n" +
//                "             let data=resp.data.data\n" +
//                "             this.#tableName#=data\n"+
//                "        }\n" +
//                "      });";
//
//        String axiosPostCodeTpl = "axios.post(   common.baseURL + \"/#tableName#\",#dataForm#).then((resp) => {\n" +
//                "        if (resp && resp.code === 200) {\n" +
//                "             let data=resp.data.data\n" +
//                "             this.#tableName#=data\n"+
//                "        }\n" +
//                "      });";
//        axiosGetCode = axiosGetCodeTpl.replace("#tableName#", tableName);
//        axiosPostCode = axiosPostCodeTpl.replace("#tableName#", tableName)
//                .replace("#dataForm#", jsonAllFiled);
//
//    }
//
//    public static String gen(Object object) {
//        String tableName = getTableName(object);
//        String jsonAllFiled = ObjectToJson.Object2JsonAllFiled(object);
//
//        String axiosCode = "axios.get(   common.baseURL + \"/#tableName#\").then((resp) => {\n" +
//                "        if (resp && resp.code === 200) {\n" +
//                "             let data=resp.data.data" +
//                "        }\n" +
//                "      });";
//
//        String axiosPostCode = "axios.post(   common.baseURL + \"/#tableName#\",#dataForm#).then((resp) => {\n" +
//                "        if (resp && resp.code === 200) {\n" +
//                "             let data=resp.data.data" +
//                "        }\n" +
//                "      });";
//        String replace = axiosCode.replace("#tableName#", tableName);
//        String replace1 = axiosPostCode.replace("#tableName#", tableName)
//                .replace("#dataForm#", jsonAllFiled);
//        return replace;
//    }

//    public static <T> String getTableName(T obj) {
//        String tableName = obj.getClass().getSimpleName();
//        tableName = StringUtils.underscoreNameLower(tableName);
//        return tableName;
//    }

    public static String getTableName(Object obj) {
        String tableName = obj.getClass().getSimpleName();
        tableName = StrUtil.underscoreNameLower(tableName);
        return tableName;
    }
}
